<template>
  <!-- <el-button @click="sendDataToServer">测试：给后端发送消息。</el-button> -->
  <div id="app">
    <div class="container">
      <!-- 创建一个canvas画布 npmn-js是通过canvas实现绘图的，并设置ref让vue获取到element -->
      <div class="bpmn-container">
        <div class="bpmn-canvas" ref="canvas"></div>
        <!-- 工具栏显示的地方 -->
        <div class="bpmn-js-properties-panel" id="js-properties-panel"></div>
      </div>

      <!-- 把操作按钮写在这里面 -->
      <div class="action">
        <el-upload action class="upload-demo" :before-upload="openBpmn">
          <el-button icon="el-icon-folder-opened">导入</el-button>
        </el-upload>
        <el-button class="new" icon="el-icon-circle-plus" @click="newDiagram"
          >新建</el-button
        >
        <el-button icon="el-icon-download" @click="downloadBpmn"
          >导出bpmn标准xml</el-button
        >
        <a hidden ref="downloadLink"></a>
      </div>
    </div>
  </div>
</template>
<script>
import BpmnModeler from "bpmn-js/lib/Modeler";
// 工具栏相关
import propertiesProviderModule from "bpmn-js-properties-panel/lib/provider/activiti";
import propertiesPanelModule from "bpmn-js-properties-panel";
import avtivitiModdleDescriptor from "activiti-bpmn-moddle/resources/activiti";
import { xmlStr } from "../mock/xmlStr";

// 汉化
import customTranslate from "@/components/bpmn/customTranslate";

export default {
  data() {
    return {
      bpmnModeler: null,
      canvas: null,
      xmlStr: "",
      // ws是否启动
      wsIsRun: false,
      // 定义ws对象
      webSocket: null,
      definitionXML: "",
      // ws请求链接（类似于ws后台地址）
      ws: "",
      // ws定时器对象
      wsTimer: null,
      query: {
        deploymentId: "",
        resourceName: "",
        instanceId: "",
      },
    };
  },
  created() {
    debugger;
    this.query = this.$route.query;
    this.getDefinitionXML();
    this.xmlStr = xmlStr;
    // this.wsIsRun = true;
    // this.wsInit();
  },
  async mounted() {},
  methods: {
    getHighLine() {
      this.$store.dispatch("getHighLine", this.query.instanceId).then((res) => {
        this.createNewDiagram(this.definitionXML);
        this.buildBPMNColor(res.obj);
      });
    },
    getDefinitionXML() {
      let param = {
        deploymentId: this.query.deploymentId,
        resourceName: this.query.resourceName,
      };
      this.$store.dispatch("getDefinitionXML", param).then((res) => {
        this.definitionXML = res;
        this.init();
        this.createNewDiagram(this.definitionXML);
        this.getHighLine();
      });
    },
    newDiagram() {
      this.createNewDiagram(this.xmlStr);
    },
    downloadBpmn() {
      this.bpmnModeler.saveXML({ format: true }, (err, xml) => {
        if (!err) {
          // 获取文件名
          const name = `${this.getFilename(xml)}.bpmn`;
          // 将文件名以及数据交给下载方法
          this.download({ name: name, data: xml });
        }
      });
    },
    openBpmn(file) {
      const reader = new FileReader();
      // 读取File对象中的文本信息，编码格式为UTF-8
      reader.readAsText(file, "utf-8");
      reader.onload = () => {
        //读取完毕后将文本信息导入到Bpmn建模器
        this.createNewDiagram(reader.result);
      };
      return false;
    },

    getFilename(xml) {
      let start = xml.indexOf("process");
      let filename = xml.substr(start, xml.indexOf(">"));
      filename = filename.substr(filename.indexOf("id") + 4);
      filename = filename.substr(0, filename.indexOf('"'));
      return filename;
    },

    download({ name = "diagram.bpmn", data }) {
      // 这里就获取到了之前设置的隐藏链接
      const downloadLink = this.$refs.downloadLink;

      // 把数据转换为URI，下载要用到的
      const encodedData = encodeURIComponent(data);

      if (data) {
        // 将数据给到链接
        downloadLink.href =
          "data:application/bpmn20-xml;charset=UTF-8," + encodedData;
        // 设置文件名
        downloadLink.download = name;
        // 触发点击事件开始下载
        downloadLink.click();
      }
    },

    async init() {
      // 获取画布 element
      this.canvas = this.$refs.canvas;

      // 将汉化包装成一个模块
      const customTranslateModule = {
        translate: ["value", customTranslate],
      };

      // 创建Bpmn对象
      this.bpmnModeler = new BpmnModeler({
        // 设置bpmn的绘图容器为上门获取的画布 element
        container: this.canvas,

        // 加入工具栏支持
        // propertiesPanel: {
        //   parent: "#js-properties-panel",
        // },
        additionalModules: [
          // 工具栏模块
          // propertiesProviderModule,
          // propertiesPanelModule,
          // 汉化模块
          customTranslateModule,
        ],
        moddleExtensions: {
          // activiti: avtivitiModdleDescriptor,
        },
      });

      await this.createNewDiagram(this.definitionXML);
    },
    async createNewDiagram(bpmn) {
      debugger;
      // 将字符串转换成图显示出来;
      await this.bpmnModeler.importXML(bpmn, (err) => {
        if (err) {
          this.$Message.error("打开模型出错,请确认该模型符合Bpmn2.0规范");
        }
      });
    },
    buildBPMNColor(data) {
      var colorJson = this.getByColor(data);
      let _this = this;
      setTimeout(function () {
        for (var i in colorJson) {
          debugger;
          _this.setColor(colorJson[i]);
        }
      }, 200);
    },
    setColor(json) {
      debugger;
      var modeling = this.bpmnModeler.get("modeling");
      var elementRegistry = this.bpmnModeler.get("elementRegistry");
      var elementToColor = elementRegistry.get(json.name);
      if (elementToColor) {
        modeling.setColor([elementToColor], {
          stroke: json.stroke,
          fill: json.fill,
        });
      }
    },

    getByColor(data) {
      var ColorJson = [];

      for (var k in data["highLine"]) {
        var par = {
          name: data["highLine"][k],
          stroke: "green",
          fill: "green",
        };
        ColorJson.push(par);
      }

      for (var k in data["highPoint"]) {
        var par = {
          name: data["highPoint"][k],
          stroke: "gray",
          fill: "#eae9e9",
        };
        ColorJson.push(par);
      }

      // for (var k in data["iDo"]) {
      //   var par = {
      //     name: data["iDo"][k],
      //     stroke: "green",
      //     fill: "#a3d68e",
      //   };
      //   ColorJson.push(par);
      // }

      for (var k in data["waitingToDo"]) {
        var par = {
          name: data["waitingToDo"][k],
          stroke: "green",
          fill: "yellow",
        };
        ColorJson.push(par);
      }

      return ColorJson;
    },

    /**
     * 初始化ws
     */
    wsInit() {
      // debugger;
      // if ('WebSocket' in window) {

      // }
      console.log(this.query);
      const wsuri =
        "ws://127.0.0.1:8090/ws/test?instanceId=" +
        this.query.instanceId +
        "&deploymentId=" +
        this.query.deploymentId +
        "&resourceName=" +
        this.query.resourceName;
      this.ws = wsuri;
      if (!this.wsIsRun) return;
      // 销毁ws
      this.wsDestroy();
      // 初始化ws
      this.webSocket = new WebSocket(this.ws);
      // ws连接建立时触发
      this.webSocket.addEventListener("open", this.wsOpenHanler);
      // ws服务端给客户端推送消息
      this.webSocket.addEventListener("message", this.wsMessageHanler);
      // ws通信发生错误时触发
      this.webSocket.addEventListener("error", this.wsErrorHanler);
      // ws关闭时触发
      this.webSocket.addEventListener("close", this.wsCloseHanler);
      // 检查ws连接状态,readyState值为0表示尚未连接，1表示建立连接，2正在关闭连接，3已经关闭或无法打开
      clearInterval(this.wsTimer);
      this.wsTimer = setInterval(() => {
        if (this.webSocket.readyState === 1) {
          clearInterval(this.wsTimer);
        } else {
          console.log("ws建立连接失败");
          // this.wsInit();
        }
      }, 3000);
    },
    wsOpenHanler() {
      console.log("ws建立连接成功");
    },
    wsMessageHanler(response) {
      console.log("wsMessageHanler");
      console.log(response); //const redata = JSON.parse(e.data) //console.log(redata)
      let data = JSON.parse(response.data);

      this.buildBPMNColor(data);
      // 返回消息
    },
    /**
     * ws通信发生错误
     */
    wsErrorHanler(event) {
      console.log(event, "通信发生错误");
      // this.wsInit();
    },
    /**
     * ws关闭
     */
    wsCloseHanler(event) {
      console.log(event, "ws关闭");
      // this.wsInit();
    },
    /**
     * 销毁ws
     */
    wsDestroy() {
      if (this.webSocket !== null) {
        this.webSocket.removeEventListener("open", this.wsOpenHanler);
        this.webSocket.removeEventListener("message", this.wsMessageHanler);
        this.webSocket.removeEventListener("error", this.wsErrorHanler);
        this.webSocket.removeEventListener("close", this.wsCloseHanler);
        this.webSocket.close();
        this.webSocket = null;
        clearInterval(this.wsTimer);
      }
    },
    sendDataToServer() {
      if (this.webSocket.readyState === 1) {
        this.webSocket.send(
          "来自前端的数据:生命不必每时每刻都要冲刺。低沉时，就当给自己放了一个悠长的假期"
        );
      } else {
        throw Error("服务未连接");
      }
    },
  },
};
</script>
 
<style scoped>
.bpmn-container {
  width: 100%;
  height: 100vh;
  display: flex;
}

.bpmn-canvas {
  width: calc(100% - 300px);
  height: 100vh;
}

.bpmn-js-properties-panel {
  width: 320px;
  height: inherit;
  overflow-y: auto;
}

.action1 {
  position: fixed;
  bottom: 100px;
  left: 100px;
  display: flex;
}
.action {
  position: fixed;
  bottom: 10px;
  left: 10px;
  display: flex;
}
.upload-demo {
  margin-right: 10px;
}
.el-message-box__message p {
  word-break: break-all;
}
</style>
